with My_String;

package body Classer is

   function Inferieur(X,Y : Type_Matiere ; Criteres : Type_Criteres; Position : Type_Nombre_Criteres := 1 ) return Boolean is

      function Boucler (X,Y : Type_Matiere ; Criteres : Type_Criteres ) return Boolean is
      begin
         if Position < 4  then
            return Inferieur(X,Y,Criteres,Position+1);
         else
            return False;
         end if;
      end Boucler;

   begin
      case Criteres.Tab(Position).Champ is
         when Intitule =>
            if My_String.equals(X.Intitule,Y.Intitule) then
               return boucler(X,Y,Criteres);
            else
               if Criteres.Tab(Position).Ordre = croissant then
                  return X.Intitule.Texte(1..X.Intitule.Taille) < Y.Intitule.Texte(1..Y.Intitule.Taille);
               else
                  return X.Intitule.Texte(1..X.Intitule.Taille) > Y.Intitule.Texte(1..Y.Intitule.Taille);
               end if;
            end if;

         when Coefficient =>
            if( X.Coefficient = Y.Coefficient) then
               return boucler(X,Y,Criteres);
            else
               if Criteres.Tab(Position).Ordre = croissant then
                  return X.Coefficient < Y.Coefficient;
               else
                  return X.Coefficient > Y.Coefficient;
               end if;
            end if;

         when Etat =>
            if( X.Note.Selon = Y.Note.Selon) then
               return boucler(X,Y,Criteres);
            else
               if Criteres.Tab(Position).Ordre = croissant then
                  return X.Note.Selon < Y.Note.Selon;
               else
                  return X.Note.Selon > Y.Note.Selon;
               end if;
            end if;
         when Note =>
            declare
               XN : constant Float := Matiere.Note_To_Float(X.Note);
               YN : constant Float := Matiere.Note_To_Float(Y.Note);
            begin
               if( XN = YN) then
                  return boucler(X,Y,Criteres);
               else
                  if Criteres.Tab(Position).Ordre = croissant then
                     return XN < YN;
                  else
                     return XN > YN;
                  end if;
               end if;
            end;
      end Case;

   end Inferieur;

   procedure Classer(Diplome : in out Type_Diplome; Criteres : Type_Criteres) is
      Test : Boolean := False;
      Aux : Type_Matiere;
   begin
      loop
         Test := False;
         For I in 2..Diplome.Matieres.Nombre loop
            if Inferieur(Diplome.Matieres.Tab(I),Diplome.Matieres.Tab(I-1),Criteres) then
               Aux := Diplome.Matieres.Tab(I);
               Diplome.Matieres.Tab(I) := Diplome.Matieres.Tab(I-1);
               Diplome.Matieres.Tab(I-1) := Aux;
               Test := True;
            end if;
         end loop;
         if Test = False then
            exit;
         end if;
      end loop;
   end Classer;

end Classer;